package com.googlecode.pacswitch.conditions;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.Enumeration;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

import com.googlecode.pacswitch.Condition;
import com.googlecode.pacswitch.ObjectFactory;
import com.googlecode.pacswitch.PString;
import com.googlecode.pacswitch.PacSwitch;

/**
 * @author Andrey Pavlenko
 */
@XmlType(name = "LocalHost", namespace = ObjectFactory.CNS)
public class LocalHost implements Condition {
    private PString _name;
    private PString _pattern;

    @XmlAttribute
    public PString getName() {
        return _name;
    }

    public void setName(final PString name) {
        _name = name;
    }

    @XmlAttribute
    public PString getPattern() {
        return _pattern;
    }

    public void setPattern(final PString pattern) {
        _pattern = pattern;
    }

    @Override
    public boolean apply(final PacSwitch ps,
            final AsynchronousSocketChannel clientSocket) {
        final String name;
        final boolean pattern;
        PString pstring = getName();

        if (pstring != null) {
            name = pstring.resolve(ps, clientSocket);
            pattern = false;
        } else {
            pstring = getPattern();

            if (pstring != null) {
                name = pstring.resolve(ps, clientSocket);
                pattern = true;
            } else {
                ps.getConfig()
                        .getLog()
                        .warn("Neither name nor pattern attribute is specified");
                return false;
            }
        }

        try {
            final Enumeration<NetworkInterface> interfaces = NetworkInterface
                    .getNetworkInterfaces();

            while (interfaces.hasMoreElements()) {
                final Enumeration<InetAddress> addresses = interfaces
                        .nextElement().getInetAddresses();

                while (addresses.hasMoreElements()) {
                    final String host = addresses.nextElement()
                            .getCanonicalHostName();
                    if (pattern) {
                        if (host.matches(name)) {
                            return true;
                        }
                    } else {
                        if (host.equals(name)) {
                            return true;
                        }
                    }
                }
            }
        } catch (final SocketException ex) {
            ps.getConfig().getLog().error("Error occurred", ex);
        }

        return false;
    }
}
